package com.yunqi.starter.excel.core.convert;

import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import cn.idev.excel.converters.Converter;
import cn.idev.excel.enums.CellDataTypeEnum;
import cn.idev.excel.metadata.GlobalConfiguration;
import cn.idev.excel.metadata.data.ReadCellData;
import cn.idev.excel.metadata.data.WriteCellData;
import cn.idev.excel.metadata.property.ExcelContentProperty;
import cn.idev.excel.util.StringUtils;
import com.yunqi.starter.excel.core.annotations.DictFormat;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Excel 数据字典转换器
 *
 * @author 芋道源码
 */
@Slf4j
public class DictConvert implements Converter<Object> {

    @Override
    public Class<?> supportJavaTypeKey() {
        return Object.class;
    }

    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return null;
    }

    @Override
    public Object convertToJavaData(ReadCellData readCellData, ExcelContentProperty contentProperty,
                                    GlobalConfiguration globalConfiguration) {
        DictFormat anno = getAnnotation(contentProperty.getField());
        String type = anno.dictType();
        String label = readCellData.getStringValue();

        String value = "";
        if (StringUtils.isBlank(type)) {
            value = reverseByExp(label, anno.readConverterExp(), anno.separator());
        }
        return Convert.convert(contentProperty.getField().getType(), value);
    }

    @Override
    public WriteCellData<String> convertToExcelData(Object object, ExcelContentProperty contentProperty,
                                                    GlobalConfiguration globalConfiguration) {
        // 空时，返回空
        if (object == null) {
            return new WriteCellData<>("");
        }
        DictFormat anno = getAnnotation(contentProperty.getField());
        String type = anno.dictType();
        String value = Convert.toStr(object);

        String label = "";
        if (StringUtils.isBlank(type)) {
            label = convertByExp(value, anno.readConverterExp(), anno.separator());
        }
        // 生成 Excel 小表格
        return new WriteCellData<>(label);

    }

    private DictFormat getAnnotation(Field field) {
        return AnnotationUtil.getAnnotation(field, DictFormat.class);
    }


    /**
     * 解析导出值 0=男,1=女,2=未知
     *
     * @param propertyValue 参数值
     * @param converterExp  翻译注解
     * @param separator     分隔符
     * @return 解析后值
     */
    public static String convertByExp(String propertyValue, String converterExp, String separator) {
        if (StrUtil.isEmpty(propertyValue) || StrUtil.isEmpty(converterExp)) {
            return StringUtils.EMPTY;
        }

        // 构建转换规则的Map（原key=原value）
        Map<String, String> converterMap = Arrays.stream(converterExp.split(","))
                .map(s -> s.split("=", 2)) // 限制分割为两部分
                .filter(arr -> arr.length == 2 && StringUtils.isNotBlank(arr[0]))
                .collect(Collectors.toMap(
                        arr -> arr[0].trim(),
                        arr -> arr[1].trim(),
                        (existing, replacement) -> existing // 处理重复键保留第一个
                ));

        // 流式处理所有匹配项
        return Arrays.stream(propertyValue.split(separator))
                .map(s -> converterMap.getOrDefault(s.trim(), s)) // 保留未匹配的原值
                .filter(StringUtils::isNotBlank)
                .collect(Collectors.joining(separator));
    }

    /**
     * 反向解析值 男=0,女=1,未知=2
     *
     * @param propertyValue 参数值
     * @param converterExp  翻译注解
     * @param separator     分隔符
     * @return 解析后值
     */
    public static String reverseByExp(String propertyValue, String converterExp, String separator) {
        if (StrUtil.isEmpty(propertyValue) || StrUtil.isEmpty(converterExp)) {
            return StringUtils.EMPTY;
        }

        // 将转换规则转换为Map提高查询效率
        Map<String, String> converterMap = Arrays.stream(converterExp.split(","))
                .map(s -> s.split("=", 2)) // 限制分割为两部分
                .filter(arr -> arr.length == 2)
                .collect(Collectors.toMap(
                        arr -> arr[1],   // 原value作为新key
                        arr -> arr[0]    // 原key作为新value
                ));

        // 处理包含分隔符的情况
        if (StrUtil.contains(propertyValue, separator)) {
            return Arrays.stream(propertyValue.split(separator))
                    .map(s -> converterMap.getOrDefault(s, ""))
                    .filter(StringUtils::isNotBlank)
                    .collect(Collectors.joining(separator));
        }

        // 处理单个值的情况
        return converterMap.getOrDefault(propertyValue, "");
    }

}
